package com.ruoyi.web.controller.approve;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.Approve;
import com.ruoyi.common.core.domain.entity.ApproveMission;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ApproveService;
import com.ruoyi.system.service.resp.ApproveDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author：liyouxin
 * @date：2023/8/15 12:50
 */
@RestController
@RequestMapping("/approve/approve")
public class ApproveController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(ApproveController.class);

    @Resource
    private ApproveService approveService;

    @Resource
    private SysUserMapper sysUserMapper;

    @GetMapping("/listByActivityId")
    public TableDataInfo listByActivityId(Long activityId, String activityType) {

        startPage();
        List<Approve> list = approveService.getApproveByActivityd(activityId, activityType);
        return getDataTable(fillToDTO(list));
    }

    @GetMapping("/getByActivityId")
    public AjaxResult getMissionByActivityId(ApproveMission approveMission) {
        return success(approveService.getByActivityd(approveMission.getActivityId(), approveMission.getActivityType()));
    }

    @GetMapping("/listByMissionId")
    public TableDataInfo listByMissionId(Long missionId) {
        List<Approve> list = approveService.getByMissionId(missionId);
        return getDataTable(fillToDTO(list));
    }

    @GetMapping("/listNeedMe")
    public TableDataInfo listNeedMe() {
        startPage();
        Long userId = SecurityUtils.getUserId();
        List<ApproveMission> approveMissions = approveService.getNeedMeByUserId(userId);
        return getDataTable(approveMissions);
    }

    @GetMapping("/listNeedMeAlready")
    public TableDataInfo listNeedMeAlready() {
        startPage();
        Long userId = SecurityUtils.getUserId();
        List<ApproveMission> approveMissions = approveService.getNeedMeAlreadyByUserId(userId);
        return getDataTable(approveMissions);
    }

    @GetMapping("/listMyApply")
    public TableDataInfo listMyApply(ApproveMission approveMission) {
        startPage();
        approveMission.setApplicant(SecurityUtils.getUserId());
        List<ApproveMission> list = approveService.getApply(approveMission);
        return getDataTable(list);
    }

    @Log(title = "提交审批", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody ApproveMission approveMission) {
        approveMission.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        approveMission.setApplicant(SecurityUtils.getUserId());
        ApproveMission created = approveService.createApproveMission(approveMission);
        return success(created);
    }

    @PostMapping("/pass")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult pass(@RequestBody Approve approve) {
        approveService.approve(approve.getId());
        return AjaxResult.success();
    }

    @PostMapping("/deny")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deny(Long id) {
        try {
            approveService.deny(id);
        } catch (Exception e) {
            log.error("审批流程出错 id {}", id, e);
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.success();
    }

    private List<ApproveDTO> fillToDTO(List<Approve> approves) {
        if (CollectionUtils.isEmpty(approves)) {
            return Collections.emptyList();
        }
        List<Long> userIds = approves.stream().filter(Objects::nonNull).map(Approve::getApprover).collect(Collectors.toList());
        userIds.addAll(approves.stream().filter(Objects::nonNull).map(Approve::getApplicant).collect(Collectors.toList()));
        List<SysUser> sysUsers = sysUserMapper.selectUserByUserIds(userIds.toArray(new Long[0]));
        Map<Long, SysUser> userMap = sysUsers.stream().filter(Objects::nonNull).collect(Collectors.toMap(SysUser::getUserId, u -> u));
        return approves.stream().map(a -> {
            ApproveDTO approveDTO = new ApproveDTO();
            approveDTO.setId(a.getId());
            approveDTO.setName(a.getName());
            approveDTO.setApprover(a.getApprover());
            approveDTO.setApproverName(Optional.ofNullable(userMap.get(a.getApprover())).map(SysUser::getNickName).orElse(null));
            approveDTO.setApplicant(a.getApplicant());
            approveDTO.setApplicantName(Optional.ofNullable(userMap.get(a.getApplicant())).map(SysUser::getNickName).orElse(null));
            approveDTO.setActivityId(a.getActivityId());
            approveDTO.setActivityType(a.getActivityType());
            approveDTO.setApproved(a.getApproved());
            approveDTO.setCanEdit(SecurityUtils.isAdmin(SecurityUtils.getUserId()) || ("审批中".equals(a.getStatus()) && SecurityUtils.getUserId().equals(a.getApprover())));
            approveDTO.setApproveTime(a.getApproveTime());
            approveDTO.setStatus(a.getStatus());
            approveDTO.setCreateTime(a.getCreateTime());
            approveDTO.setCreateBy(a.getCreateBy());
            approveDTO.setUpdateBy(a.getUpdateBy());
            approveDTO.setUpdateTime(a.getUpdateTime());
            approveDTO.setMissionId(a.getMissionId());
            return approveDTO;
        }).collect(Collectors.toList());
    }
}
